package org.filetransfer.file_transfer_java_backend.service;

import org.filetransfer.file_transfer_java_backend.entity.File;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Service
public class FilePreviewService {

    @Autowired
    private ShareItemService shareItemService;

    /**
     * 根据文件类型返回预览数据
     */
    public Map<String, Object> getFilePreview(String code, String md5) {
        Optional<File> fileOptional = shareItemService.getShareItemFile(code, md5);
        if (fileOptional.isEmpty()) {
            throw new RuntimeException("文件未找到");
        }

        File file = fileOptional.get();
        String fileName = file.getFileName();
        String filePath = file.getFilePath();
        String fileExtension = getFileExtension(fileName).toLowerCase();

        Map<String, Object> previewData = new HashMap<>();
        previewData.put("fileName", fileName);
        previewData.put("fileSize", file.getFileSize());
        previewData.put("md5", file.getMd5());

        try {
            switch (getFileType(fileExtension)) {
                case IMAGE:
                    previewData.put("type", "image");
                    previewData.put("data", getImagePreview(filePath));
                    break;
                case ARCHIVE:
                    previewData.put("type", "archive");
                    previewData.put("data", getArchivePreview(filePath, fileExtension));
                    break;
                case TEXT:
                    previewData.put("type", "text");
                    previewData.put("data", getTextPreview(filePath));
                    break;
                case VIDEO:
                    previewData.put("type", "video");
                    previewData.put("data", getVideoPreview(filePath, fileName));
                    break;
                case AUDIO:
                    previewData.put("type", "audio");
                    previewData.put("data", getAudioPreview(filePath, fileName));
                    break;
                case PDF:
                    previewData.put("type", "pdf");
                    previewData.put("data", getPdfPreview(filePath));
                    break;
                default:
                    previewData.put("type", "unknown");
                    previewData.put("data", getUnknownFilePreview(fileName, fileExtension));
                    break;
            }
        } catch (Exception e) {
            previewData.put("type", "error");
            previewData.put("data", Map.of("error", "预览失败: " + e.getMessage()));
        }

        return previewData;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return "";
        }
        return fileName.substring(lastDotIndex + 1);
    }

    /**
     * 根据文件扩展名判断文件类型
     */
    private FileType getFileType(String extension) {
        Set<String> imageExtensions = Set.of("jpg", "jpeg", "png", "gif", "bmp", "webp", "svg");
        Set<String> archiveExtensions = Set.of("zip", "rar", "7z", "tar", "gz", "bz2", "xz");
        Set<String> textExtensions = Set.of("txt", "md", "json", "xml", "csv", "log", "java", "js", "ts", "html", "css", "yaml", "yml", "properties");
        Set<String> videoExtensions = Set.of("mp4", "avi", "mkv", "mov", "wmv", "flv", "webm", "m4v");
        Set<String> audioExtensions = Set.of("mp3", "wav", "flac", "aac", "ogg", "wma", "m4a");
        Set<String> pdfExtensions = Set.of("pdf");

        if (imageExtensions.contains(extension)) {
            return FileType.IMAGE;
        } else if (archiveExtensions.contains(extension)) {
            return FileType.ARCHIVE;
        } else if (textExtensions.contains(extension)) {
            return FileType.TEXT;
        } else if (videoExtensions.contains(extension)) {
            return FileType.VIDEO;
        } else if (audioExtensions.contains(extension)) {
            return FileType.AUDIO;
        } else if (pdfExtensions.contains(extension)) {
            return FileType.PDF;
        } else {
            return FileType.UNKNOWN;
        }
    }

    /**
     * 获取图片预览 - 返回base64编码
     */
    private Map<String, Object> getImagePreview(String filePath) throws IOException {
        byte[] imageBytes = Files.readAllBytes(Paths.get(filePath));
        String base64 = Base64.getEncoder().encodeToString(imageBytes);
        
        Map<String, Object> result = new HashMap<>();
        result.put("base64", base64);
        result.put("mimeType", Files.probeContentType(Paths.get(filePath)));
        
        return result;
    }

    /**
     * 获取压缩文件预览 - 返回文件树结构
     */
    private Map<String, Object> getArchivePreview(String filePath, String extension) throws IOException {
        Map<String, Object> result = new HashMap<>();
        
        if ("zip".equals(extension)) {
            result.put("fileTree", getZipFileTree(filePath));
        } else {
            // 对于其他压缩格式，暂时返回基本信息
            result.put("fileTree", List.of(Map.of(
                "name", "不支持的压缩格式预览",
                "type", "info",
                "message", "当前仅支持ZIP文件的预览"
            )));
        }
        
        return result;
    }

    /**
     * 获取ZIP文件的文件树结构
     */
    private List<Map<String, Object>> getZipFileTree(String filePath) throws IOException {
        List<Map<String, Object>> fileTree = new ArrayList<>();
        
        try (ZipFile zipFile = new ZipFile(filePath)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("name", entry.getName());
                fileInfo.put("size", entry.getSize());
                fileInfo.put("isDirectory", entry.isDirectory());
                fileInfo.put("lastModified", entry.getLastModifiedTime().toInstant());
                
                fileTree.add(fileInfo);
            }
        }
        
        return fileTree;
    }

    /**
     * 获取文本文件预览
     */
    private Map<String, Object> getTextPreview(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        long fileSize = Files.size(path);
        
        Map<String, Object> result = new HashMap<>();
        
        // 如果文件太大，只读取前几行
        if (fileSize > 1024 * 1024) { // 1MB
            try (Stream<String> lines = Files.lines(path)) {
                List<String> previewLines = lines.limit(100).toList();
                result.put("content", String.join("\n", previewLines));
                result.put("truncated", true);
                result.put("totalSize", fileSize);
            }
        } else {
            result.put("content", Files.readString(path));
            result.put("truncated", false);
            result.put("totalSize", fileSize);
        }
        
        return result;
    }

    /**
     * 获取视频文件预览
     */
    private Map<String, Object> getVideoPreview(String filePath, String fileName) {
        Map<String, Object> result = new HashMap<>();
        result.put("streamUrl", "/api/preview/stream/" + fileName);
        result.put("mimeType", getMimeTypeByExtension(getFileExtension(fileName)));
        result.put("message", "视频文件需要通过流媒体播放");
        
        return result;
    }

    /**
     * 获取音频文件预览
     */
    private Map<String, Object> getAudioPreview(String filePath, String fileName) {
        Map<String, Object> result = new HashMap<>();
        result.put("streamUrl", "/api/preview/stream/" + fileName);
        result.put("mimeType", getMimeTypeByExtension(getFileExtension(fileName)));
        result.put("message", "音频文件需要通过流媒体播放");
        
        return result;
    }

    /**
     * 获取PDF文件预览
     */
    private Map<String, Object> getPdfPreview(String filePath) {
        Map<String, Object> result = new HashMap<>();
        result.put("downloadUrl", "/api/share/" + filePath);
        result.put("message", "PDF文件需要下载后查看");
        
        return result;
    }

    /**
     * 获取未知文件类型预览
     */
    private Map<String, Object> getUnknownFilePreview(String fileName, String extension) {
        Map<String, Object> result = new HashMap<>();
        result.put("extension", extension);
        result.put("message", "不支持的文件类型预览");
        result.put("suggestion", "请下载文件进行查看");
        
        return result;
    }

    /**
     * 根据文件扩展名获取MIME类型
     */
    private String getMimeTypeByExtension(String extension) {
        return switch (extension.toLowerCase()) {
            case "mp4" -> "video/mp4";
            case "avi" -> "video/x-msvideo";
            case "mkv" -> "video/x-matroska";
            case "mov" -> "video/quicktime";
            case "wmv" -> "video/x-ms-wmv";
            case "flv" -> "video/x-flv";
            case "webm" -> "video/webm";
            case "mp3" -> "audio/mpeg";
            case "wav" -> "audio/wav";
            case "flac" -> "audio/flac";
            case "aac" -> "audio/aac";
            case "ogg" -> "audio/ogg";
            case "wma" -> "audio/x-ms-wma";
            default -> "application/octet-stream";
        };
    }

    /**
     * 文件类型枚举
     */
    private enum FileType {
        IMAGE, ARCHIVE, TEXT, VIDEO, AUDIO, PDF, UNKNOWN
    }
}
